package com.seems.janggu;

import java.lang.ref.WeakReference;

import com.seems.janggu.HitInfo.HitItem;
import com.seems.janggu.R;

import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class MainActivity extends Activity implements OnTouchListener,
		OnClickListener {

	private int mDungSound;
	private SoundPool mSoundPool;
	private int mDdaSound;
	private int mGiSound;
	private int mGungSound;
	final private String TAG = "MainActivity";

	private Button mDungButton;
	private Button mGiButton;
	private Button mGungButton;
	private Button mDdaButton;
	private HitInfo mHitInfo;

	final private int TIMER_TICK = 10;

	final private int STATE_RECORDING = 1;
	final private int STATE_PLAYING = 2;
	final private int STATE_STOP = 3;
	private int mState = STATE_STOP;
	private Button mPlayButton;
	private Button mStopButton;
	private Button mRecordButton;
	private ScoreView mView;
	private long mPrevBukMilliSec;
	// private long mCurrentRecording = 0;
	private long mCurrentMilliSec;
	private Handler mHandler;
	private int mPlayIndex = 0;
	protected long mPreviousMilliSec;
	private int mDoongSound;
	private SeekBar mSeekBar;
	protected int mBukFrequency = 700;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_main);

		mView = (ScoreView) findViewById(R.id.janggu_view);
		mView.setBukFrequency(700);

		mSeekBar = (SeekBar) findViewById(R.id.buk_frequency_seekbar);
		mSeekBar.setProgress(25);
		mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				mBukFrequency = (progress + 10) * 20;
				mView.setBukFrequency(mBukFrequency);

			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub

			}

		});

		mDungButton = (Button) findViewById(R.id.dung_button);
		mDungButton.setOnTouchListener(this);

		mGiButton = (Button) findViewById(R.id.gi_button);
		mGiButton.setOnTouchListener(this);

		mGungButton = (Button) findViewById(R.id.gung_button);
		mGungButton.setOnTouchListener(this);

		mDdaButton = (Button) findViewById(R.id.dda_button);
		mDdaButton.setOnTouchListener(this);

		mPlayButton = (Button) findViewById(R.id.play_button);
		mPlayButton.setOnClickListener(this);

		mStopButton = (Button) findViewById(R.id.stop_button);
		mStopButton.setOnClickListener(this);

		mRecordButton = (Button) findViewById(R.id.record_button);
		mRecordButton.setOnClickListener(this);

		mCurrentMilliSec = 0;
		mPreviousMilliSec = 0;
		mPrevBukMilliSec = 0;

		mHitInfo = HitInfo.getInstance();

		mHandler = new MainHandler(this);

		mHandler.sendEmptyMessage(0);
	}

	static class MainHandler extends Handler {
		WeakReference<MainActivity> thisActivity;

		MainHandler(MainActivity activity) {
			thisActivity = new WeakReference<MainActivity>(activity);
		}

		public void handleMessage(Message msg) {
			HitItem item;
			MainActivity activity = thisActivity.get();

			if(activity == null) return;
			
			if (activity.mState != activity.STATE_STOP) {
				if (activity.mPreviousMilliSec == 0) {
					activity.mPreviousMilliSec = System.currentTimeMillis();
				}
				activity.mCurrentMilliSec += System.currentTimeMillis()
						- activity.mPreviousMilliSec;
				activity.mPreviousMilliSec = System.currentTimeMillis();
			}

			if (activity.mState == activity.STATE_PLAYING) {
				item = activity.mHitInfo.getHitItem(activity.mPlayIndex);
				if (item != null
						&& Math.abs(item.getMilliSec()
								- activity.mCurrentMilliSec) < 20) {
					Log.d(activity.TAG,
							""
									+ Math.abs(item.getMilliSec()
											- activity.mCurrentMilliSec));
					activity.playSound(item.getHitType(), item.getPressure());
					activity.mPlayIndex++;
				}
			}

			activity.mView.updateScoreView(activity.mCurrentMilliSec);
			if (activity.mCurrentMilliSec != 0
					&& activity.mCurrentMilliSec % activity.mBukFrequency < 20) {
				if (Math.abs(activity.mCurrentMilliSec
						- activity.mPrevBukMilliSec) > 100) {
					activity.mSoundPool.play(activity.mDoongSound, 1.0f, 1.0f,
							0, 0, 1.0f);
					activity.mPrevBukMilliSec = activity.mCurrentMilliSec;
				}
			}

			item = activity.mHitInfo.getNextHitItem(activity.mCurrentMilliSec);
			if (item != null) {
				long remainMilliSec = item.getMilliSec()
						- activity.mCurrentMilliSec;
				if (remainMilliSec < activity.TIMER_TICK) {
					sendEmptyMessageDelayed(0, remainMilliSec);
				} else {
					sendEmptyMessageDelayed(0, activity.TIMER_TICK);
				}
			} else {
				sendEmptyMessageDelayed(0, activity.TIMER_TICK);
			}
		}

	}

	private void playSound(int index, float volume) {
		switch (index) {
		case HitItem.HIT_TYPE_DUNG:
			mSoundPool.play(mDungSound, volume, volume, 0, 0, 1.0f);
			break;
		case HitItem.HIT_TYPE_GI:
			mSoundPool.play(mGiSound, volume, volume, 0, 0, 1.0f);
			break;
		case HitItem.HIT_TYPE_GUNG:
			mSoundPool.play(mGungSound, volume, volume, 0, 0, 1.0f);
			break;
		case HitItem.HIT_TYPE_DDA:
			mSoundPool.play(mDdaSound, volume, volume, 0, 0, 1.0f);
		default:
			break;
		}
	}

	@Override
	public void onClick(View v) {
		if (v == mPlayButton) {
			mSeekBar.setEnabled(false);
			mState = STATE_PLAYING;
			mPlayIndex = 0;
			mCurrentMilliSec = 0;
			mPreviousMilliSec = 0;
			mHandler.sendEmptyMessage(0);
			mRecordButton.setEnabled(false);
			mStopButton.setEnabled(true);
			mPlayButton.setEnabled(false);
		} else if (v == mStopButton) {
			mSeekBar.setEnabled(true);
			mState = STATE_STOP;
			mPlayIndex = 0;
			mRecordButton.setEnabled(true);
			mStopButton.setEnabled(false);
			mPlayButton.setEnabled(true);
		} else if (v == mRecordButton) {
			mSeekBar.setEnabled(false);
			mState = STATE_RECORDING;
			mHitInfo.reset();
			mCurrentMilliSec = 0;
			mPreviousMilliSec = 0;
			mRecordButton.setEnabled(false);
			mStopButton.setEnabled(true);
			mPlayButton.setEnabled(false);
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {

		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			if (v == mGungButton) {
				playSound(HitItem.HIT_TYPE_GUNG, event.getPressure());
				if (mState == STATE_RECORDING) {
					mHitInfo.addHitItem(HitItem.HIT_TYPE_GUNG,
							event.getPressure(), mCurrentMilliSec);
				}
			} else if (v == mGiButton) {
				playSound(HitItem.HIT_TYPE_GI, event.getPressure());
				if (mState == STATE_RECORDING) {
					mHitInfo.addHitItem(HitItem.HIT_TYPE_GI,
							event.getPressure(), mCurrentMilliSec);
				}
			} else if (v == mDungButton) {
				playSound(HitItem.HIT_TYPE_DUNG, event.getPressure());
				if (mState == STATE_RECORDING) {
					mHitInfo.addHitItem(HitItem.HIT_TYPE_DUNG,
							event.getPressure(), mCurrentMilliSec);
				}
			} else if (v == mDdaButton) {
				playSound(HitItem.HIT_TYPE_DDA, event.getPressure());
				if (mState == STATE_RECORDING) {
					mHitInfo.addHitItem(HitItem.HIT_TYPE_DDA,
							event.getPressure(), mCurrentMilliSec);
				}
			}
		}

		return false;
	}

	@Override
	protected void onPause() {
		mSoundPool.release();
		super.onPause();
	}

	@Override
	protected void onResume() {
		mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);

		mDungSound = mSoundPool.load(getApplicationContext(), R.raw.dung, 1);
		mDdaSound = mSoundPool.load(getApplicationContext(), R.raw.dda, 1);
		mGiSound = mSoundPool.load(getApplicationContext(), R.raw.gi, 1);
		mGungSound = mSoundPool.load(getApplicationContext(), R.raw.gung, 1);
		mDoongSound = mSoundPool.load(getApplicationContext(), R.raw.doong, 1);
		super.onResume();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		// getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

}
